package com.example.mapperapi.util;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;

/**
 * bean 工具类
 * 1. 包装类型的拷贝
 * 2. 对象类型的拷贝
 *
 * @author 徐鑫
 * @date 2023/03/25
 */
@Slf4j
public final class BeanUtil {

    private static final Set<Class<?>> baseClassSet;

    static {
        baseClassSet = new HashSet<>();
        baseClassSet.add(Integer.class);
        baseClassSet.add(String.class);
        baseClassSet.add(Double.class);
        baseClassSet.add(Long.class);
    }

    /**
     * 基本包装类型->Integer
     *
     * @param source 源
     * @param target 目标
     */
    public static void copyToInteger(Object source, Integer target) {
        try {
            if (source == null || target == null) {
                return;
            }
            if (source instanceof Integer) {
                Integer tmp = (Integer) source;
                Field field = target.getClass().getDeclaredField("value");
                field.setAccessible(true);
                field.set(target, tmp);
            }
            if (source instanceof Long) {
                long sourceTmp = (Long) source;
                int targetTmp = (int) sourceTmp;
                Field field = target.getClass().getDeclaredField("value");
                field.setAccessible(true);
                field.set(target, targetTmp);
            }
            if (source instanceof Double) {
                int targetTmp = ((Double) source).intValue();
                Field field = target.getClass().getDeclaredField("value");
                field.setAccessible(true);
                field.set(target, targetTmp);
            }
            if (source instanceof String) {
                double tmp = Double.parseDouble((String) source);
                Field field = target.getClass().getDeclaredField("value");
                field.setAccessible(true);
                field.set(target, (int) tmp);
            }
        } catch (Exception e) {
            log.error("BeanUtil.copyToInteger出错:{} can not cast to Integer!", source.getClass());
        }
    }

    /**
     * 基本包装类型->Long
     *
     * @param source 源
     * @param target 目标
     */
    public static void copyToLong(Object source, Long target) {
        try {
            if (source == null || target == null) {
                return;
            }
            if (source instanceof Long) {
                Field field = target.getClass().getDeclaredField("value");
                field.setAccessible(true);
                field.set(target, (Long) source);
            }
            if (source instanceof Integer) {
                int sourceTmp = (Integer) source;
                Field field = target.getClass().getDeclaredField("value");
                field.setAccessible(true);
                field.set(target, (long) sourceTmp);
            }
            if (source instanceof Double) {
                Field field = target.getClass().getDeclaredField("value");
                field.setAccessible(true);
                field.set(target, ((Double) source).longValue());
            }
            if (source instanceof String) {
                double targetTmp = Double.parseDouble((String) source);
                Field field = target.getClass().getDeclaredField("value");
                field.setAccessible(true);
                field.set(target, (long) targetTmp);
            }
        } catch (Exception e) {
            log.error("BeanUtil.copyToLong出错:{} can not cast to Long!", source.getClass());
        }
    }

    /**
     * 基本包装类型->Double
     *
     * @param source 源
     * @param target 目标
     */
    public static void copyToDouble(Object source, Double target) {
        try {
            if (source == null || target == null) {
                return;
            }
            if (source instanceof Double) {
                Double tmp = (Double) source;
                Field field = target.getClass().getDeclaredField("value");
                field.setAccessible(true);
                field.set(target, tmp);
            }
            if (source instanceof Long) {
                double sourceTmp = ((Long) source).doubleValue();
                Field field = target.getClass().getDeclaredField("value");
                field.setAccessible(true);
                field.set(target, sourceTmp);
            }
            if (source instanceof Integer) {
                double targetTmp = (Integer) source;
                Field field = target.getClass().getDeclaredField("value");
                field.setAccessible(true);
                field.set(target, targetTmp);
            }
            if (source instanceof String) {
                double targetTmp = Double.parseDouble((String) source);
                Field field = target.getClass().getDeclaredField("value");
                field.setAccessible(true);
                field.set(target, targetTmp);
            }
        } catch (Exception e) {
            log.error("BeanUtil.copyToDouble出错:{} can not cast to Double!", source.getClass());
        }
    }

    /**
     * 基本包装类型->String
     *
     * @param source 源
     * @param target 目标
     */
    public static void copyToString(Object source, String target) {
        try {
            if (source == null || target == null) {
                return;
            }
            Field field = String.class.getDeclaredField("value");
            field.setAccessible(true);
            Object tmp = field.get(source.toString());
            field.set(target, tmp);
        } catch (Exception e) {
            log.error("BeanUtil.copyToString出错:{} can not cast to String!", source.getClass());
        }
    }


    /**
     * 基类包装类型->基本包装类型
     *
     * @param source 源
     * @param target 目标
     */
    public static void baseTypeCopyToBaseType(Object source, Object target) {
        try {
            if (source == null || target == null) {
                return;
            }
            if (!baseClassSet.contains(source.getClass()) || !baseClassSet.contains(target.getClass())) {
                return;
            }
            if (target instanceof Integer) {
                copyToInteger(source, (Integer) target);
            } else if (target instanceof Double) {
                copyToDouble(source, (Double) target);
            } else if (target instanceof String) {
                copyToString(source, (String) target);
            } else if (target instanceof Long) {
                copyToLong(source, (Long) target);
            }
        } catch (Exception e) {
            log.error("BeanUtil.baseTypeCopyToBaseType出错:{} can not cast to {}!", source.getClass(), target.getClass());
        }
    }


    /**
     * 根据class类型，copy source的值
     *
     * @param source      源
     * @param targetClass 目标类
     * @return {@code Object}
     */
    public static Object baseTypeCopyToNewBaseType(Object source, Class<?> targetClass) {
        try {
            if (source == null || targetClass == null) {
                return null;
            }
            if (!baseClassSet.contains(targetClass)) {
                return null;
            }
            if (Integer.class.equals(targetClass)) {
                Integer target = 0;
                copyToInteger(source, target);
                return target;
            } else if (Double.class.equals(targetClass)) {
                Double target = 0D;
                copyToDouble(source, target);
                return target;
            } else if (String.class.equals(targetClass)) {
                String target = "";
                copyToString(source, target);
                return target;
            } else if (Long.class.equals(targetClass)) {
                Long target = 0L;
                copyToLong(source, target);
                return target;
            }
        } catch (Exception e) {
            log.error("BeanUtil.baseTypeCopyToNewBaseType出错:{} can not cast to {}!", source.getClass(), targetClass);
        }
        return null;
    }


}
